package com.tianji.learning.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.api.client.remark.RemarkClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.ReplyDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.ReplyPageQuery;
import com.tianji.learning.domain.vo.ReplyVO;
import com.tianji.learning.enums.QuestionStatus;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import com.tianji.learning.service.IInteractionReplyService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动问题的回答或评论 服务实现类
 * </p>
 *
 * @author xjs
 */
@Slf4j
@Service
public class InteractionReplyServiceImpl extends ServiceImpl<InteractionReplyMapper, InteractionReply> implements IInteractionReplyService {

    @Autowired
    @Lazy
    private IInteractionQuestionService questionService;
    @Autowired
    private UserClient userClient;
    @Autowired
    RemarkClient remarkClient;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addReply(ReplyDTO dto) {
        InteractionReply reply = BeanUtil.copyProperties(dto, InteractionReply.class);
        reply.setUserId(UserContext.getUser());
        reply.setHidden(false);
        reply.setCreateTime(LocalDateTime.now());
        reply.setUpdateTime(LocalDateTime.now());
        this.save(reply);
        // 如果是一个answer，修改问题的最近回答的id和回答的次数
        if(dto.getAnswerId() == null){
            InteractionQuestion question = questionService.getById(dto.getQuestionId());
            if(question == null){
                log.error("找不到question：{}", dto.getQuestionId());
                throw  new BizIllegalException("网络异常");
            }
            question.setLatestAnswerId(reply.getId());
            question.setAnswerTimes(question.getAnswerTimes()==null?1:question.getAnswerTimes()+1);
            question.setUpdateTime(LocalDateTime.now());
            questionService.updateById(question);
        }else{
            // 累加回答下面的评论次数
            // 找到回答
            InteractionReply answer = this.getById(dto.getAnswerId());
            if(answer == null){
                log.error("找不到reply：{}", dto.getAnswerId());
                throw  new BizIllegalException("网络异常");
            }
            answer.setReplyTimes(answer.getReplyTimes()==null?1:answer.getReplyTimes()+1);
            answer.setUpdateTime(LocalDateTime.now());
            this.updateById(answer);
        }
        // 如果是学生提交，需要问题的状态未未查看
        if(dto.getIsStudent()!=null && dto.getIsStudent()){
            InteractionQuestion question = new InteractionQuestion();
            question.setId(dto.getQuestionId());
            question.setStatus(QuestionStatus.UN_CHECK.getValue());
            question.setUpdateTime(LocalDateTime.now());
            questionService.updateById(question);
        }
    }

    @Override
    public PageDTO<ReplyVO> queryReplyPage(ReplyPageQuery query, boolean forAdmin) {
        // 1.问题id和回答id至少要有一个，先做参数判断
        Long questionId = query.getQuestionId();
        Long answerId = query.getAnswerId();
        if (questionId == null && answerId == null) {
            throw new BadRequestException("问题或回答id不能都为空");
        }
        // 标记当前是查询问题下的回答
        boolean isQueryAnswer = questionId != null;
        // 2.分页查询reply
        Page<InteractionReply> page = lambdaQuery()
                .eq(isQueryAnswer, InteractionReply::getQuestionId, questionId)
                .eq(InteractionReply::getAnswerId, isQueryAnswer ? 0L : answerId)
                .eq(!forAdmin, InteractionReply::getHidden, false)
                .page(query.toMpPageDefaultSortByCreateTimeDesc());
//                .page(query.toMpPage( // 先根据点赞数排序，点赞数相同，再按照创建时间排序
//                        new OrderItem(DATA_FIELD_NAME_LIKED_TIME, false),
//                        new OrderItem(DATA_FIELD_NAME_CREATE_TIME, true))
//                );
        List<InteractionReply> records = page.getRecords();
        if (CollUtils.isEmpty(records)) {
            return PageDTO.empty(page);
        }
        // 3.数据处理，需要查询：提问者信息、回复目标信息、当前用户是否点赞
        Set<Long> userIds = new HashSet<>();
        Set<Long> answerIds = new HashSet<>();
        Set<Long> targetReplyIds = new HashSet<>();
        // 3.1.获取提问者id 、回复的目标id、当前回答或评论id（统计点赞信息）
        for (InteractionReply r : records) {
            if(!r.getAnonymity() || forAdmin) {
                // 非匿名
                userIds.add(r.getUserId());
            }
            targetReplyIds.add(r.getTargetReplyId());
            answerIds.add(r.getId());
        }
        // 3.2.查询目标回复，如果目标回复不是匿名，则需要查询出目标回复的用户信息
        targetReplyIds.remove(0L);
        targetReplyIds.remove(null);
        if(targetReplyIds.size() > 0) {
            List<InteractionReply> targetReplies = listByIds(targetReplyIds);
            Set<Long> targetUserIds = targetReplies.stream()
                    .filter(Predicate.not(InteractionReply::getAnonymity).or(r -> forAdmin))
                    .map(InteractionReply::getUserId)
                    .collect(Collectors.toSet());
            userIds.addAll(targetUserIds);
        }
        // 3.3.查询用户
        Map<Long, UserDTO> userMap = new HashMap<>(userIds.size());
        if(userIds.size() > 0) {
            List<UserDTO> users = userClient.queryUserByIds(userIds);
            userMap = users.stream().collect(Collectors.toMap(UserDTO::getId, u -> u));
        }
        // 3.4.查询用户点赞状态 TODO
        List<Long> replyIds = records.stream().map(InteractionReply::getId).collect(Collectors.toList());
        replyIds = remarkClient.isBizLiked(replyIds, "QA");

        // 4.处理VO
        List<ReplyVO> list = new ArrayList<>(records.size());
        for (InteractionReply r : records) {
            // 4.1.拷贝基础属性
            ReplyVO v = BeanUtils.toBean(r, ReplyVO.class);
            list.add(v);
            // 4.2.回复人信息
            if(!r.getAnonymity() || forAdmin){
                UserDTO userDTO = userMap.get(r.getUserId());
                if (userDTO != null) {
                    v.setUserIcon(userDTO.getIcon());
                    v.setUserName(userDTO.getName());
                    v.setUserType(userDTO.getType());
                }
            }
            // 4.3.如果存在评论的目标，则需要设置目标用户信息
            if(r.getTargetReplyId() != null){
                UserDTO targetUser = userMap.get(r.getTargetUserId());
                if (targetUser != null) {
                    v.setTargetUserName(targetUser.getName());
                }
            }
            //TODO 4.4.点赞状态
            Optional<Long> any = replyIds.stream().filter(replyId -> Objects.equals(replyId, r.getId())).findAny();
            if(any.isPresent()){
                v.setLiked(true);
            }
        }
        return new PageDTO<>(page.getTotal(), page.getPages(), list);
    }
    private Boolean findLikedBizId(List<String> likedBizIds, Long bizId) {
        if(CollectionUtils.isEmpty(likedBizIds)){
            return false;
        }
        Optional<String> any = likedBizIds.stream().filter(id -> Objects.equals(Long.parseLong(id), bizId)).findAny();
        return any.isPresent();
    }
}
